package com.grad.webstudy.service.impl;

import com.grad.webstudy.constants.TokenConstants;
import com.grad.webstudy.enums.ExceptionEnums;
import com.grad.webstudy.exceptions.CustomException;
import com.grad.webstudy.model.Token;
import com.grad.webstudy.model.User;
import com.grad.webstudy.service.TokenService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Description: token接口的实现类，使用redis保存token信息
 * @Author: zjf
 * @Date: 2020/1/19 14:13.
 */
@Component
public class TokenServiceImpl implements TokenService {

    @Resource
    RedisTemplate<String, Token> redisTemplate;

    @Override
    public Token createToken(User user) {
        String userId = String.valueOf(user.getId());
        String key = UUID.randomUUID().toString();
        //todo 有机会将token转换为小写
        Token tokenEntity = new Token(userId, Base64Utils.encodeToString(key.getBytes()), user);
        redisTemplate.opsForValue().set(TokenConstants.TOKEN_LOGIN_CACHE_KEY_PREFIX + key, tokenEntity, TokenConstants.TOKEN_EXPIRES_MINUTES, TimeUnit.MINUTES);
        return tokenEntity;
    }

    @Override
    public boolean checkToken(String token) {
        if (StringUtils.isEmpty(token)) {
            return false;
        }
        String key = TokenConstants.TOKEN_LOGIN_CACHE_KEY_PREFIX + new String(Base64Utils.decodeFromString(token));
        Token tokenresult = redisTemplate.opsForValue().get(key);
        if (tokenresult == null || StringUtils.isEmpty(tokenresult.getToken())) {
            return false;
        }
        return tokenresult.getToken().equals(token);
    }

    @Override
    public Token getToken(String key) {
        if (!StringUtils.isEmpty(key)) {
            //对加密的字符串进行解密
            key = TokenConstants.TOKEN_LOGIN_CACHE_KEY_PREFIX + new String(Base64Utils.decodeFromString(key));
            System.out.println("解密后字符串：" + key);
            Token tokenEntity = redisTemplate.opsForValue().get(key);

            if (Objects.isNull(tokenEntity)){
                throw new CustomException(ExceptionEnums.TOKEN_INVALID.getCode(),
                        ExceptionEnums.TOKEN_INVALID.getMessage());
            }

            return tokenEntity;
        }
        throw new CustomException(ExceptionEnums.TOKEN_INVALID.getCode(),
                ExceptionEnums.TOKEN_INVALID.getMessage());
    }

    @Override
    public void deleteToken(String token) {
        String key = TokenConstants.TOKEN_LOGIN_CACHE_KEY_PREFIX + new String(Base64Utils.decodeFromString(token));
        redisTemplate.delete(key);
    }

    @Override
    public void refresh(String token) {
        String key = TokenConstants.TOKEN_LOGIN_CACHE_KEY_PREFIX + new String(Base64Utils.decodeFromString(token));
        Long time = redisTemplate.getExpire(key, TimeUnit.MINUTES);
        if (time != -2 && time < TokenConstants.TOKEN_THRESHOLD) {
            redisTemplate.expire(key, TokenConstants.TOKEN_EXPIRES_MINUTES, TimeUnit.MINUTES);
        }
    }
}
